<?php

namespace app\admin\library;

use fast\Random;
use fast\Tree;
use think\Cookie;
use think\Hook;
use think\Request;
use think\Session;
use WeChatPay\Builder;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Util\PemUtil;
use WeChatPay\Formatter;
use WeChatPay\Crypto\AesGcm;
use think\Log;


class Wxpay
{
    /**
     * 微信小程序支付
     * @param $out_no
     * @param $amount
     * @param $subject
     * @param $time
     * @param $notify
     * @return void
     */
    public function wxPay($out_no,$amount,$subject,$notify,$type='jsapi',$wx_open_id)
    {
        // 商户号
        $merchantId = config('site.mch_id');
        $appid = config('site.wxappid');

        // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
        $merchantPrivateKeyFilePath = 'file://'.ROOT_PATH.'/addons/wxpay/apiclient_key.pem';
        //echo $merchantPrivateKeyFilePath;die;
        $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);
        // 「商户API证书」的「证书序列号」
        $merchantCertificateSerial = config('site.serial_no');

        // 从本地文件中加载「微信支付平台证书」，用来验证微信支付应答的签名
        $platformCertificateFilePath = 'file://'.ROOT_PATH.'/addons/wxpay/wechatpay_5499138DC7FDB514815461A314FFCA01A160FD27.pem';
        $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
        // 从「微信支付平台证书」中获取「证书序列号」
        $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath);
        // 构造一个 APIv3 客户端实例
        $instance = Builder::factory([
            'mchid'      => $merchantId,
            'serial'     => $merchantCertificateSerial,
            'privateKey' => $merchantPrivateKeyInstance,
            'certs'      => [
                $platformCertificateSerial => $platformPublicKeyInstance,
            ],
        ]);
        try {
            $resp = $instance
                ->chain('v3/pay/transactions/jsapi')
                ->post(['json' => [
                    'mchid'        => $merchantId,
                    'out_trade_no' => $out_no,
                    'appid'        => $appid,
                    'description'  => $subject,
                    'notify_url'   => $notify,
                    'amount'       => [
                        'total'    => $amount*100,
                        'currency' => 'CNY'
                    ],
                    'payer'       => [
                        'openid'    => $wx_open_id
                    ],
                ]]);
            if($resp->getStatusCode() == 200)
            {
                $return['code'] = 1;
                $datas = json_decode($resp->getBody(),true);
                $params = [
                    'appId'     =>$appid,
                    'timeStamp' => (string)Formatter::timestamp(),
                    'nonceStr'  => Formatter::nonce(),
                    'package'   => 'prepay_id='.$datas["prepay_id"],
                ];
                $params += ['paySign' => Rsa::sign(
                    Formatter::joinedByLineFeed(...array_values($params)),
                    $merchantPrivateKeyInstance
                ), 'signType' => 'RSA'];
                $return['data'] = $params;
            }else
            {
                $return['code'] = -1;
            }
            //return $return;
        } catch (\Exception $e) {
            // 进行错误处理
            echo $e->getMessage(), PHP_EOL;
            if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
                $r = $e->getResponse();
                //echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
                //echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
                $return['code'] = -2;
                $return['data'] = $r->getReasonPhrase();
            }else
            {
                $return['code'] = -3;
            }
        }
        return $return;
    }
    
    
   
    /**
     * 回调检测
     * @param $inWechatpaySignature
     * @param $inWechatpayTimestamp
     * @param $inWechatpaySerial
     * @param $inWechatpayNonce
     * @param $inBody
     * @return void
     */
    public function checkSign($inWechatpaySignature,$inWechatpayTimestamp,$inWechatpayNonce,$inBody)
    {
        // 从本地文件中加载「微信支付平台证书」，用来验证微信支付应答的签名
        $platformCertificateFilePath = 'file://'.ROOT_PATH.'/addons/wxpay/wechatpay_5499138DC7FDB514815461A314FFCA01A160FD27.pem';
        $platformPublicKeyInstance = Rsa::from(file_get_contents($platformCertificateFilePath), Rsa::KEY_TYPE_PUBLIC);
        // 根据通知的平台证书序列号，查询本地平台证书文件，这里是自己生成的证书
        // 检查通知时间偏移量，允许5分钟之内的偏移
        // 检查通知时间偏移量，允许5分钟之内的偏移
        $timeOffsetStatus = 300 >= abs(Formatter::timestamp() - (int)$inWechatpayTimestamp);
        $timeOffsetStatus = true;
        

        $verifiedStatus = Rsa::verify(
        // 构造验签名串
            Formatter::joinedByLineFeed($inWechatpayTimestamp, $inWechatpayNonce, $inBody),
            $inWechatpaySignature,
            $platformPublicKeyInstance
        );
        Log::info($inBody);
        
        if ($timeOffsetStatus && $verifiedStatus) {
            // 转换通知的JSON文本消息为PHP Array数组
            $inBodyArray = (array)json_decode($inBody, true);
            // 使用PHP7的数据解构语法，从Array中解构并赋值变量

            $ciphertext = $inBodyArray['resource']['ciphertext'];
            $nonce = $inBodyArray['resource']['nonce'];
            $aad = $inBodyArray['resource']['associated_data'];

            // 加密文本消息解密
            $inBodyResource = AesGcm::decrypt($ciphertext, config('site.mch_secret'), $nonce, $aad);
            // 把解密后的文本转换为PHP Array数组
            $inBodyResourceArray = (array)json_decode($inBodyResource, true);
            print_r($inBodyResourceArray);// 打印解密后的结果
            return $inBodyResourceArray;
        }
        return false;
    }
}